<?php

declare(strict_types=1);

namespace App\CustHub\Mapper;

use App\CustHub\Model\ChContact;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\Config\Annotation\Value;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Collection;
use Hyperf\Database\Model\Model;
use Mine\Abstracts\AbstractMapper;
use Mine\MineModel;
use function Hyperf\Collection\data_get;

class ChContactMapper extends AbstractMapper
{

    #[Value('cache.default.prefix')]
    protected string $prefix;

    public function assignModel()
    {
        $this->model = ChContact::class;
    }

    /**
     * 获取客户信息
     * @param mixed $id
     * @return ChContact|Model|string|Builder|null
     */
    public function findById(mixed $id): ChContact|Model|string|Builder|null
    {
        return $this->model::query()
            ->where('id',$id)
            ->first();
    }

    #[Cacheable(prefix: 'robot_contact_info', value: '#{robotId}:#{userId}', ttl: 15 * 60)]
    public function findByRobotIdAndUserId(int $robotId,string $userId): ChContact|Model|string|Builder|null
    {
        return $this->model::query()
            ->select(['id','robot_id','call_name','uid','main_uid','nickname','avatar','corp_short_name','user_id','remark','desc','company_remark','gender','source','add_customer_time','last_send_msg_time','create_time'])
            ->where('robot_id',$robotId)
            ->where('user_id',$userId)
            ->first();
    }

    public function rmCache(int $robotId,string $userId): void
    {
        $redis = redis();
        $keys[] = $this->prefix . 'robot_contact_info:'.$robotId.':'.$userId;
        $redis->del($keys);
    }

    /**
     * 根据user_id获取客户信息
     * @param string $userId
     * @param $uid
     * @return Collection
     */
    public function findByUserIdAndUid(string $userId, $uid)
    {
        return $this->model::query()
            ->where('user_id',$userId)
            ->where('uid',$uid)
            ->get();
    }

    /**
     * 获取重复客户ID
     * @param array $robotIds
     * @return array
     */
    public function getDuplicateUserIds(array $robotIds): array
    {
        return $this->model::query()
            ->whereIn('robot_id',$robotIds)
            ->groupBy('user_id')
            ->havingRaw('COUNT(robot_id) >= 2')
            ->pluck('user_id')->toArray();
    }

    /**
     * 检测重复客户
     * @param array $robotIds
     * @return array|Collection
     */
    public function detectDuplicateContact(array $robotIds): array|Collection
    {
        $list = $this->model::query()
            ->selectRaw('id,nickname,avatar,corp_short_name corp_name,user_id,robot_id,is_wechat')
            ->with(['robot'=>function ($query) {
                $query->select(['id','nickname','avatar','corp_name']);
            }])
            ->whereIn('user_id',function ($query) use ($robotIds){
                $query->select('user_id')
                    ->from('ch_contact')
                    ->whereIn('robot_id',$robotIds)
                    ->groupBy('user_id')
                    ->havingRaw('COUNT(robot_id) >= 2');
            })->get();

        return $list;
    }

    /**
     * 获取重复客户数量
     * @param array $params
     * @return int
     */
    public function getUniqueContactCount(array $params): int
    {
        return $this->handleSearch($this->model::query(),$params)->distinct()->count('user_id');
    }

    public function findBatchByRobotIdAndUserIds(array $robotUserGroups): Collection
    {
        $query = $this->model::query()
            ->select(['robot_id', 'user_id', 'nickname as name', 'avatar'])
            ->where(function ($query) use ($robotUserGroups) {
                foreach ($robotUserGroups as $robotId => $userIds) {
                    $query->orWhere(function ($q) use ($robotId, $userIds) {
                        $q->where('robot_id', $robotId)
                            ->whereIn('user_id', $userIds);
                    });
                }
            });

        return $query->get()
            ->groupBy('robot_id')
            ->mapWithKeys(fn($items, $robotId) => [
                $robotId => $items->keyBy('user_id')
            ]);
    }

    /**
     * 搜索处理器.
     */
    public function handleSearch(Builder $query, array $params,bool $isLoad=true): Builder
    {
        $keyword = data_get($params, 'keyword');
        $keywords = data_get($params, 'keywords');
        $corpTag = data_get($params, 'corp_tag', '');
        $corpTag = !is_array($corpTag)?json_decode($corpTag, true):$corpTag;

        $smartTag = data_get($params, 'smart_tag', '');
        $smartTag = !is_array($smartTag)?json_decode($smartTag, true):$smartTag;

        $isWithRemarks = data_get($params, 'is_with_remarks');
        $gender = data_get($params, 'gender');

        $robotIds = data_get($params, 'robot_ids');
        $robotGroupId = data_get($params,'robot_group_id','');
        if(empty($robotIds) && filled($robotGroupId) && $robotGroupId != -1){
            //机器人分组
            $robotIds = container()->get(ChRobotMapper::class)->getIdsByGroupId($params['uid'],$robotGroupId);
        }
        if($isLoad){
            $query->with(['robot'=>function ($query) {
                $query->select(['id','nickname','avatar','corp_name','login_status']);
            },'corpTags' => function ($query) {
                $query->select(['id', 'name'])->orderBy('create_time', 'desc');
            }, 'smartTags' => function ($query) {
                $query->select(['id', 'name'])->orderBy('created_at', 'desc');
            }]);
        }

        $query->withPermission((int)$params['uid']);

//        if(!empty($params['corp_id'])){
//            $query->where('corp_id',$params['corp_id']);
//        }

        if(!empty($robotIds) || $robotGroupId == 0){
            if(isJson($robotIds)){
                $robotIds = json_decode($robotIds);
            }
            $query->whereIn('robot_id',$robotIds);
        }

        if(!empty($params['mobile'])){
            $mobile = $params['mobile'];
            $query->whereHas('mobileList',function ($query) use ($mobile){
               $query->where('mobile',$mobile);
            });
        }

        if(isset($params['is_call_name']) && filled($params['is_call_name'])){
            if($params['is_call_name'] == 1){
                $query->where('call_name','<>','');
            }else{
                $query->where('call_name','');
            }
        }

        if(isset($params['wechat_type']) && filled($params['wechat_type'])){
            $query->where('is_wechat',$params['wechat_type']);
        }

        if(isset($params['is_white']) && filled($params['is_white'])){
            $query->where('is_white',$params['is_white']);
        }

        if(isset($params['is_black']) && filled($params['is_black'])){
            $query->where('is_black',$params['is_black']);
        }


        if(!empty($keywords)){
            $keywords = json_decode($keywords,true);
            $includeMatchType = $keywords['include_match_type'];
            $includeKeywords = $keywords['include_keywords'];
            if ($includeMatchType == 0) {
                $query->where(function ($query) use ($includeKeywords){
                    $query->where(function ($query) use ($includeKeywords){
                        // 含任意一个关键词
                        foreach ($includeKeywords as $keyword) {
                            $query->orWhere('nickname', 'like', "%{$keyword}%");
                        }
                    })->orWhere(function ($query) use ($includeKeywords){
                        // 含任意一个关键词
                        foreach ($includeKeywords as $keyword) {
                            $query->orWhere('remark', 'like', "%{$keyword}%");
                        }
                    });

                });
            } else {
                $query->where(function ($query) use ($includeKeywords){
                    // 含所有关键词
                    $query->where(function ($query) use ($includeKeywords){
                        // 含任意一个关键词
                        foreach ($includeKeywords as $keyword) {
                            $query->where('nickname', 'like', "%{$keyword}%");
                        }
                    })->orWhere(function ($query) use ($includeKeywords){
                        // 含任意一个关键词
                        foreach ($includeKeywords as $keyword) {
                            $query->where('remark', 'like', "%{$keyword}%");
                        }
                    });
                });
            }
        }


        if (!empty($corpTag)) {

            $includeMatchType = data_get($corpTag, 'include_match_type', 0);
            $includeTagIds = data_get($corpTag, 'include_tag_ids');

            if(!empty($includeTagIds)){
                switch ($includeMatchType) {
                    case 0:
                        //满足任意一个标签
                        $query->whereHas('corpTags', function ($query) use ($includeTagIds) {
                            $query->whereIn('corp_tag_id', $includeTagIds);
                        });
                        break;
                    case 1:
                        //满足所有标签
                        $query->whereHas('corpTags', function ($query) use ($includeTagIds) {
                            $query->whereIn('corp_tag_id', $includeTagIds);
                        }, '=', count($includeTagIds));
                        break;
                    default:
                        //未打标签
                        $query->doesntHave('corpTags');
                        break;
                }
            }

            $excludeSwitch = data_get($corpTag, 'exclude_switch', 0);
            if ($excludeSwitch) {
                $excludeMatchType = data_get($corpTag, 'exclude_match_type', 0);
                $excludeTagIds = data_get($corpTag, 'exclude_tag_ids');
                if(!empty($excludeTagIds)){
                    switch ($excludeMatchType) {
                        case 0:
                            //满足任意一个标签
                            $query->whereDoesntHave('corpTags', function ($query) use ($excludeTagIds) {
                                $query->whereIn('corp_tag_id', $excludeTagIds);
                            });
                            break;
                        case 1:
                            //满足所有标签
                            $query->whereDoesntHave('corpTags', function ($query) use ($excludeTagIds) {
                                $query->whereIn('corp_tag_id', $excludeTagIds)->havingRaw('COUNT(*) = ?', [count($excludeTagIds)]);
                            });
                            break;
                        default:
                            //已设置标签的
                            $query->has('corpTags');
                            break;
                    }
                }
            }

        }

        if (!empty($smartTag)) {

            $includeMatchType = data_get($smartTag, 'include_match_type', 0);
            $includeTagIds = data_get($smartTag, 'include_tag_ids');

            if(!empty($includeTagIds)){
                switch ($includeMatchType) {
                    case 0:
                        //满足任意一个标签
                        $query->whereHas('smartTags', function ($query) use ($includeTagIds) {
                            $query->whereIn('smart_tag_id', $includeTagIds);
                        });
                        break;
                    case 1:
                        //满足所有标签
                        $query->whereHas('smartTags', function ($query) use ($includeTagIds) {
                            $query->whereIn('smart_tag_id', $includeTagIds);
                        }, '=', count($includeTagIds));
                        break;
                    default:
                        //未打标签
                        $query->doesntHave('smartTags');
                        break;
                }
            }

            $excludeSwitch = data_get($smartTag, 'exclude_switch', 0);
            if ($excludeSwitch) {
                $excludeMatchType = data_get($smartTag, 'exclude_match_type', 0);
                $excludeTagIds = data_get($smartTag, 'exclude_tag_ids');

                if(!empty($excludeTagIds)){
                    switch ($excludeMatchType) {
                        case 0:
                            //满足任意一个标签
                            $query->whereDoesntHave('smartTags', function ($query) use ($excludeTagIds) {
                                $query->whereIn('smart_tag_id', $excludeTagIds);
                            });
                            break;
                        case 1:
                            //满足所有标签
                            $query->whereDoesntHave('smartTags', function ($query) use ($excludeTagIds) {
                                $query->whereNotIn('smart_tag_id', $excludeTagIds)->havingRaw('COUNT(*) = ?', [count($excludeTagIds)]);
                            });
                            break;
                        default:
                            //已设置标签的
                            $query->has('smartTags');
                            break;
                    }
                }
            }
        }
        $query->when(filled($isWithRemarks),function ($query) use ($isWithRemarks,$params){
            $query->where(function ($query) use ($isWithRemarks,$params){
                if($isWithRemarks == 0){
                    $query->where('remark','');
                }else{
                    $remark_type =  data_get($params, 'remark_type',2);
                    $remarks =  data_get($params, 'remarks');
                    if(!empty($remarks)){
                        if($remark_type == 1){
                            //包含所有
                            foreach ($remarks as $remark){
                                $query->whereLike('remark','like',$remark."%");
                            }
                        }else{
                            //包含任意
                            foreach ($remarks as $remark){
                                $query->orWhere('remark','like',$remark."%");
                            }
                        }
                    }
                }
            });
        })->when(filled($gender),function ($query) use ($gender){
           $query->where('gender',$gender);
        });

        if(!empty($keyword)){
            $query->where(function ($query) use ($keyword){
               $query->where('nickname','like',"%{$keyword}%")->orWhere('remark','like',"%$keyword%");
            });
        }

        if(!empty($params['add_start_time']) && !empty($params['add_end_time'])){

            $query->whereBetween('create_time', [strtotime($params['add_start_time']), strtotime($params['add_end_time'])]);
        }

        if(!empty($params['friend_loss_start_time']) && !empty($params['friend_loss_end_time'])){
            $query->whereBetween('friend_loss_time', [strtotime($params['friend_loss_start_time']), strtotime($params['friend_loss_end_time'])]);
        }

        if(isset($params['status']) && filled($params['status'])){
            $query->where('status',$params['status']);
        }

        return $query;
    }

}